import edu.auctionmart.User
import edu.auctionmart.Role
import edu.auctionmart.Profile
import edu.auctionmart.Feedback
import edu.auctionmart.Auction
import edu.auctionmart.Feedback
/**
 * User controller.
 */
class UserController {
	
	def authenticateService
	def userService

	// the delete, save and update actions only accept POST requests
	static Map allowedMethods = [delete: 'POST', save: 'POST', update: 'POST']
	
	static navigation = [
		[group: 'tabs', action: 'myAccount', title: 'My Account', order: 0]
	]

	def index = {
		redirect action: list, params: params
	}
	
	def myAccount = {

		def principal = authenticateService.principal()
		String name = principal.getUsername()
		def userInstance = User.findByUsername(name)
		
		def feedbackReceivedResults = userService.getFeedbackReceivedForUser(userInstance, params)
		def feedbackGivenResults = userService.getFeedbackGivenForUser(userInstance, params)
		
		def feedbackReceivedTotal = userService.getFeedbackReceivedTotalForUser(userInstance)
		def feedbackGivenTotal = userService.getFeedbackGivenTotalForUser(userInstance)
				
		List<Auction> winningAuctionsList = new ArrayList<Auction>()
		List<Auction> sellingAuctionsList = new ArrayList<Auction>()
		
		def winningAuctions = Auction.findAllByWinner(userInstance)
		for (Auction auction : winningAuctions) {
			def allFeedback = Feedback.findAllByAuction(auction);
			if (allFeedback.size() == 0)
				winningAuctionsList.add(auction)
			else if (allFeedback.size() == 1) {
				def feedback = allFeedback.get(0);		
				if (feedback.leftBy != userInstance)
					winningAuctionsList.add(auction)
			}
		}
		
		def sellingAuctions = Auction.findAllBySeller(userInstance)
		for (Auction auction : sellingAuctions) {
			def allFeedback = Feedback.findAllByAuction(auction);
			if (allFeedback.size() == 0 && auction.winner != null)
				sellingAuctionsList.add(auction)
			else if (allFeedback.size() == 1) {
				def feedback = allFeedback.get(0);		
				if (feedback.leftBy != userInstance)
					sellingAuctionsList.add(auction)
			}
		}
	

		render(view:"myAccount", model: [userInstance: userInstance, 
			feedbackReceivedList: feedbackReceivedResults, feedbackGivenList: feedbackGivenResults,
			feedbackReceivedTotal: feedbackReceivedTotal, feedbackGivenTotal: feedbackGivenTotal,
			winningAuctionsList: winningAuctionsList, sellingAuctionsList: sellingAuctionsList])
	}
	
	def updateFeedbackReceived = {

		def principal = authenticateService.principal()
		String name = principal.getUsername()
		def userInstance = User.findByUsername(name)
		
		def feedbackReceivedResults = userService.getFeedbackReceivedForUser(userInstance, params)
		def feedbackReceivedTotal = userService.getFeedbackReceivedTotalForUser(userInstance)
		
		render(template:"templateFeedbackReceived", model: [feedbackReceivedList: feedbackReceivedResults, feedbackReceivedTotal: feedbackReceivedTotal])
	}
	
	def updateFeedbackGiven = {

		def principal = authenticateService.principal()
		String name = principal.getUsername()
		def userInstance = User.findByUsername(name)
		
		def feedbackGivenResults = userService.getFeedbackGivenForUser(userInstance, params)
		def feedbackGivenTotal = userService.getFeedbackGivenTotalForUser(userInstance)

		render(template:"templateFeedbackGiven", model: [feedbackGivenList: feedbackGivenResults, feedbackGivenTotal: feedbackGivenTotal])
	}

	def list = {
		if (!params.max) {
			params.max = 10
		}
		[personList: User.list(params)]
	}

	def show = {
		def person = User.get(params.id)
		if (!person) {
			flash.message = "User not found with id $params.id"
			redirect action: list
			return
		}
		List roleNames = []
		for (role in person.authorities) {
			roleNames << role.authority
		}
		roleNames.sort { n1, n2 ->
			n1 <=> n2
		}
		[person: person, roleNames: roleNames]
	}

	/**
	 * Person delete action. Before removing an existing person,
	 * he should be removed from those authorities which he is involved.
	 */
	def delete = {

		def person = User.get(params.id)
		if (person) {
			def authPrincipal = authenticateService.principal()
			//avoid self-delete if the logged-in user is an admin
			if (!(authPrincipal instanceof String) && authPrincipal.username == person.username) {
				flash.message = "You can not delete yourself, please login as another admin and try again"
			}
			else {
				//first, delete this person from People_Authorities table.
				Role.findAll().each { it.removeFromPeople(person) }
				person.delete()
				flash.message = "User $params.id deleted."
			}
		}
		else {
			flash.message = "User not found with id $params.id"
		}

		redirect action: list
	}

	def edit = {

		def person = User.get(params.id)
		if (!person) {
			flash.message = "User not found with id $params.id"
			redirect action: list
			return
		}
		[person: person]
	}

	/**
	 * Person update action.
	 */
	def update = {
		
		def person = User.get(params.id)
		if (!person) {
			flash.message = "User not found with id $params.id"
			render view: 'edit', model: [person: person]
			return
		}

		long version = params.version.toLong()
		if (person.version > version) {
			person.errors.rejectValue 'version', "person.optimistic.locking.failure",
				"Another user has updated this User while you were editing."
				render view: 'edit', model: [person: person]
			return
		}

		person.properties = params
		person?.profile = params
		
		if (person.save()) {
			flash.message = "Successfully edited User ${person.username}"
			redirect action: edit, id: person.id
		}
		else {
			render view: 'edit', model: [person: person]
		}
	}

	def create = {
		def view = "createWeb"
		
		withMobileDevice {
			def device ->
			println device
			view = "createMobile"
		}
		
		render view: view, model: [person: new User(params), authorityList: Role.list()]
	}

	/**
	 * Person save action.
	 */
	def save = {UserRegistrationCommand urc ->
		
		def view = "createWeb"
		
		withMobileDevice {
			def device ->
			println device
			view = "createMobile"
		}
		
		if (urc.hasErrors()) {
			render view: view, model: [user: urc]
		}
		
		else {	
		
			def user = new User(urc.properties)
			user.profile = new Profile(urc.properties)

			user.passwd = authenticateService.encodePassword(params.passwd)
			user.enabled = true
									
			if (user.save()) {
				def roleUser = Role.findByAuthority("ROLE_USER")
				user.addToAuthorities(roleUser)
				addRoles(user)
				flash.message = "Successfully created User ${user.username}"
				redirect action: create, id: user.id
			}
			else {
				user.passwd = ""
				render view: view, model: [user: urc]
			}
		}
	}
	
	
	private void addRoles(person) {
		for (String key in params.keySet()) {
			if (key.contains('ROLE') && 'on' == params.get(key)) {
				Role.findByAuthority(key).addToPeople(person)
			}
		}
	}

	private Map buildPersonModel(person) {

		List roles = Role.list()
		roles.sort { r1, r2 ->
			r1.authority <=> r2.authority
		}
		Set userRoleNames = []
		for (role in person.authorities) {
			userRoleNames << role.authority
		}
		LinkedHashMap<Role, Boolean> roleMap = [:]
		for (role in roles) {
			roleMap[(role)] = userRoleNames.contains(role.authority)
		}

		return [person: person, roleMap: roleMap]
	}
}

class UserRegistrationCommand {
	
	String username
	String userRealName
	String passwd
	String passwdRepeat
	String email
	
	String contactPhoneNumber
	String contactEmail
	
	static constraints = {
		username(size: 3..25, blank: false, unique: true)
		userRealName(nullable: false, blank: false)
		passwd(nullable: false, blank: false)
		passwdRepeat(nullable: false, blank: false, validator: {passwd2, urc ->
			if (passwd2 != urc.passwd) {
				return 'passwordNotMatch.message'
			}			
		})
		email(nullable: false, blank: false)
		contactPhoneNumber(nullable: true, validator: {return it == null || it.toString().length() == 10 })
		contactEmail(nullable: true)
	}
}